/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package assisisw.smartcal.weathersubsystem;

import assisisw.smartcal.weathersubsystem.exceptions.ExternalServiceException;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;

/**
 *
 * @author Francesco
 */
@ApplicationScoped ()
@Named ( "weatherCache" )
@Singleton
public class WeatherCache implements IWeatherCache 
{

    // Instance Fields

    /***/
    @EJB ()
    private IExternalWeatherDataRetriever externalDataRetriever ;
    
    /***/
    private Map < String , Collection < WeatherData > > data ;
    
    // Instance Methods
    
    /***/
    public WeatherCache () {}
    
    /***/
    @PostConstruct
    public void init () 
    {
        data = new LinkedHashMap <> ( 0 ) ;
    }
    
    /**
     * @param entry 
     */
    @Override
    public synchronized void addEntry ( WeatherData entry ) 
    {
        // implement better
        String location ;
        location = entry.getLocation ().trim () ;
        checkLocationInCache ( location ) ;
        data.get ( entry.getLocation () ).add ( entry ) ;
    }
    
    /**
     * @param locationName 
     * @return
     */
    @Override
    public synchronized WeatherData getEntry ( String locationName , Date date , int hour ) 
    {
        Collection < WeatherData > ofThisLoc ;
        Iterable < WeatherData > newData ;
        WeatherData res ;
        checkLocationInCache ( locationName ) ;
        ofThisLoc = data.get ( locationName ) ;
        res = null ;
        for ( WeatherData w : ofThisLoc )
        {
            if ( w.getIniDate().getHours() >= hour && w.getEndDate ().getHours() <= hour )
            {
                res = w ;
                break ;
            }
        }
        if ( res == null )
            try 
            {
                newData = externalDataRetriever.retrieve ( locationName , "it" ) ;
                for ( WeatherData n : newData )
                {
                    addEntry ( n ) ;
                    if ( n.getIniDate().getHours() >= hour && n.getEndDate ().getHours() <= hour )
                        res = n ;
                }
            } 
            catch (ExternalServiceException ex) 
            {
                res = null ;
            }
        return res ;
    }
    
    private void checkLocationInCache ( String location ) 
    {
        if ( ! data.containsKey ( location ) )
            data.put ( location , new LinkedList <> () ) ;
    }
    
}
